#!/bin/bash

function Quit {
    [ -n "$1" ] && echo -e "\n\033[31;1mERROR: $1\033[0m!\n"
    exit 3
}

function Spreadout {
    local i=
    local service=
    local daemon=
    echo "System ${ROOT_DIR##*/} processes ..."
    for service in ${SERVICES[@]}; do
        echo "Service: \"$service\""
    done
    for i in ${!DAEMONS[@]}; do
        daemon="${DAEMONS[i]}"
        echo "Daemon: \"$daemon\""
    done
    exit 0
}

function ShowState {
    local name=$1
    local err=$2
    local total=$3
    local style=$4
    if [ '0' = "$total" ]; then
        echo -e "$name \033[32${style}mnot found\033[0m ..."
        return 254
    elif [ '0' = "$err" ]; then
        echo -e "$name \033[32${style}mrunning\033[0m ..."
        return 0
    elif [ -z "$total" -o "$total" = "$err" ]; then
        echo -e "$name \033[33${style}mstopped\033[0m!"
        return 1
    else
        echo -e "$name \033[31${style}merror\033[0m!!"
        return 255
    fi
}

function HandleServices {
    local service=
    for service in ${SERVICES[@]}; do
        echo "===> ${1}ing \"$service\" ..."
        systemctl $1 $service
        sleep 0.4
    done
}

function HandleDaemons {
    local i=
    local daemon=
    for i in ${!DAEMONS[@]}; do
        daemon="${DAEMONS[i]}"
        echo "===> ${1}ing \"$daemon\" ..."
        $WATCH_PROC $1 $daemon
        sleep 0.4
    done
}

function CheckServices {
    local err=0
    local service=
    for service in ${SERVICES[@]}; do
        systemctl status $service > /dev/null 2>/dev/null
        ShowState "Service: \"$service\"" $? || let "err=1+$err"
    done
    ShowState Services $err ${#SERVICES[@]} ';1;3'
    return $?
}

function CheckDaemons {
    local err=0
    local daemon=
    local daemon_name=
    for i in ${!DAEMONS[@]}; do
        daemon="${DAEMONS[i]}"
        daemon_name="$(basename ${daemon%% *})"
        pgrep -x ${daemon_name:0:15} > /dev/null 2>/dev/null
        ShowState "Daemon: \"$daemon\"" $? || let "err=1+$err"
    done
    ShowState Daemons $err ${#DAEMONS[@]} ';1;3'
    return $?
}

function CheckSystem {
    local i=
    local err=0
    local ret=0
    local output=
    local items=2
    for i in CheckServices CheckDaemons; do
        output=$($i)
        ret=$?
        if [ 254 -eq $ret ]; then
            let "items=${items}-1"
        elif [ 0 -lt $ret ]; then
            let "err=1+$err"
        fi
        if [ -z "$1" ]; then
            echo -e "$output" | tail -1
        else
            echo -e "$output"
        fi
    done
    ShowState "System \"${ROOT_DIR##*/}\"" $err $items ';1'
    exit $?
}

# start here
type pgrep > /dev/null || exit 1
cd $(dirname $0)
. processes || Quit 'File "processes" not found'
[ -x rc.pwatch ] || Quit 'Executalbe process not found'
WATCH_PROC="$(pwd)/rc.pwatch"
cd .. && ROOT_DIR=$(pwd) || Quit 'Change dir failed'

case $* in
    '')
        CheckSystem
        ;;
    status)
        CheckSystem detail
        ;;
    start)
        for check in CheckServices CheckDaemons; do
            $check > /dev/null 2>/dev/null
            check_ret=$?
            [ 254 -eq $check_ret ] && continue
            if [ 0 -ne $check_ret ]; then
                Handle${check#Check} start
                output=$($check)
                if [ 0 -ne $? ]; then
                    echo -e "$output"
                    Quit "${check#Check} start failed"
                fi
            fi
        done
        CheckSystem
        ;;
    stop)
        for check in CheckDaemons CheckServices; do
            $check > /dev/null 2>/dev/null
            check_ret=$?
            [ 254 -eq $check_ret ] && continue
            [ 1 -ne $check_ret ] && Handle${check#Check} stop
        done
        CheckSystem
        ;;
    startservice)
        CheckServices > /dev/null 2>/dev/null
        check_ret=$?
        if [ 254 -eq $check_ret ]; then
            CheckSystem
        elif [ 0 -ne $check_ret ]; then
            HandleServices start
            CheckSystem
        fi
        ;;
    stopdaemon)
        CheckDaemons > /dev/null 2>/dev/null
        check_ret=$?
        if [ 254 -eq $check_ret ]; then
            CheckSystem
        elif [ 1 -ne $check_ret ]; then
            HandleDaemons stop
            CheckSystem
        fi
        ;;
    list)
        Spreadout
        ;;
    *)
        echo "Usage: $0 [status|start[service]|stop[daemon]|list]"
        exit 3
        ;;
esac

